package com.scau.os.controller;

import com.scau.os.DesktopLauncher;
import com.scau.os.extension.EventSystem;
import com.scau.os.extension.MyDelegate;
import com.scau.os.extension.Utility;

import com.scau.os.fileSystem.FolderTree.FolderPane;
import com.scau.os.fileSystem.directory.*;
import com.scau.os.fileSystem.memory.Disk;
import com.scau.os.fileSystem.memory.FAT;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.control.*;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.KeyCode;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;

import java.awt.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Random;

public class filesManagerController {
    @FXML
    private BorderPane borderPane;
    @FXML
    private AnchorPane folderAnchorPanel;
    @FXML
    private ScrollPane scrollPanel;
    @FXML
    private SplitPane splitPanel;
    @FXML
    private TextField inputBox;
    @FXML
    private FlowPane fileViewPane;
    @FXML
    ScrollPane consolePane;
    @FXML
    VBox consoleBox;
    @FXML
    VBox historyBox;
    @FXML
    Label preInputBox;
    @FXML
    Label fileViewPath;

    private List<Runnable> reset=new ArrayList<>();
    private List<String> inputHistory=new ArrayList<>();
    private int curIndex=0;
    private FlowPane diskUsageView=new FlowPane();
    private  final ImageView runningDiskImage= new ImageView(Utility.getFxImage("Image/RunningDisk.png"));
    private  final ImageView diskImage=new ImageView(Utility.getFxImage("Image/Disk.png"));
    private List<Button> runningDisk=new ArrayList<>();
    private List<Button> idleDisk=new ArrayList<>();
    private String curPath;

    public void initialize() throws Exception {
        consoleBox.prefWidthProperty().bind(consolePane.widthProperty());
        consoleBox.prefHeightProperty().bind(consolePane.heightProperty());
        historyBox.prefWidthProperty().bind(consoleBox.widthProperty());
        inputBox.prefWidthProperty().bind(consoleBox.widthProperty());

        for(int i=0;i< Disk.INSTANCE.SIZE;i++){
            runningDisk.add(new Button("NO." + String.format("%03d", i),new ImageView(Utility.getFxImage("Image/RunningDisk.png"))));
        }
        for(int i=0;i< Disk.INSTANCE.SIZE;i++){
            idleDisk.add(new Button("NO." + String.format("%03d", i),new ImageView(Utility.getFxImage("Image/Disk.png"))));
        }
        changePreInputBox(DirectoryEntry.ROOT_DIRECTORY.getPath().getAbsolutePath());
        register();
        initDiskUsageView();
        setFolderTree();
        updateFileView(DirectoryEntry.ROOT_DIRECTORY);
        keyBind();
    }
    private void keyBind(){
        inputBox.setOnAction((e)->{
            String s=inputBox.getText();
            boolean flag=true;
            showInfoOnConsole("> "+s, Color.WHITE);//打印输入信息
            inputHistory.add(s);//添加进输入历史
            curIndex=inputHistory.size();

//            if(s.isBlank()==false&&s.isEmpty()==false&&s.startsWith("e")){
//                String[] parts = inputBox.getText().split(" ");
//                if(parts.length==2&&parts[0].contentEquals("execute")){
//                    flag=false;
//                    if(parts[1].contentEquals("all")){
//                        EventSystem.instance.SendEvent("demonstrationStart",null);
//
//                    }else {
//                        try {
//                            List<Byte>l= FileManager.INSTANCE.getInstructionsByPath(parts[1]);
//                            EventSystem.instance.SendEvent("executeStart",l);
//                        } catch (Exception ex) {
//                            System.err.println("非法文件执行");
//                        }
//                    }
//
//                }
//            }
//            if(flag){
//                EventSystem.instance.SendEvent("UserInput",inputBox.getText());
//            }
            EventSystem.instance.SendEvent("UserInput",inputBox.getText());
            inputBox.clear();//清空输入框
        });
        inputBox.setOnKeyPressed(e->{
            if(e.getCode()==KeyCode.UP){
                if(curIndex>0){inputBox.setText(inputHistory.get(--curIndex));}
            }else if (e.getCode()==KeyCode.DOWN){
                if(curIndex<inputHistory.size()-1){inputBox.setText(inputHistory.get(++curIndex));}
                else {inputBox.setText("");}
            }

        });
    }
    private void register() {
        EventSystem.instance.register(new MyDelegate("ShowError") {
            @Override
            public void execute(Object data) {
                show((String)data);
            }
        }).UnRegisterWhenClose(this);
        EventSystem.instance.register(new MyDelegate("ShowFileContent") {
            @Override
            public void execute(Object data) {
                showContent((String)data);
            }
        }).UnRegisterWhenClose(this);
        //用来获取当前目录树的点击对象
        EventSystem.instance.register(new MyDelegate("getSelectedTreeItem") {
            @Override
            public void execute(Object data) {
                try {
                    DirectoryEntry directoryEntry=(DirectoryEntry)data;
                    updateFileView(directoryEntry);
                    curPath=FolderPane.getInstance().getFolderTree().getSelectionModel().getSelectedItem().getValue().getPath().getAbsolutePath();
                    changePreInputBox(curPath);
                    updateBlocksOfSelectedItem(directoryEntry.getBlocks());
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
        }).UnRegisterWhenClose(this);
        //当文件分配表信息发生变动时
        EventSystem.instance.register(new MyDelegate("diskUpdate") {
            @Override
            public void execute(Object data) {
                try {
                    updateDiskUsageView();
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
        }).UnRegisterWhenClose(this);
        EventSystem.instance.register(new MyDelegate("showConsoleInfo") {
            @Override
            public void execute(Object data) {
                showInfoOnConsole(" "+(String)data,Color.RED);
            }
        }).UnRegisterWhenClose(this);
    }
    private void listener(){

    }
    private void show(String s){
        Alert alert=new Alert(Alert.AlertType.ERROR,s, ButtonType.FINISH);
        alert.showAndWait();
    }
    private void showContent(String s){
        Alert alert=new Alert(Alert.AlertType.NONE,s, ButtonType.FINISH);
        TextArea textArea=new TextArea(s);
        alert.getDialogPane().setExpandableContent(textArea);
        alert.setTitle("文件内容");
        alert.showAndWait();
    }
    private void updateDiskUsageView()  {

        List<Boolean>l= null;
        try {
            l = FAT.INSTANCE.FATStatus();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        diskUsageView.getChildren().clear();
        if(reset.size()!=0) {
            for (Runnable r :
                    reset) {
                r.run();
            }
            reset.clear();
        }
        for(int i=0;i<l.size();i++){
            Button button;
            if(!l.get(i)){
                button = runningDisk.get(i);
            }
            else {
                button = idleDisk.get(i);
            }
            diskUsageView.getChildren().add(button);
        }
    }
    private void updateBlocksOfSelectedItem(List<Integer>blocks){
        if(reset.size()!=0) {
            for (Runnable r :
                    reset) {
                r.run();
            }
            reset.clear();
        }
        List<Node> l=diskUsageView.getChildren();
        for(int i=0;i<blocks.size();i++){
            Button button=(Button)l.get(blocks.get(i));
            Node imageView=button.getGraphic();
            int tmp=i;
            reset.add(()->{
                button.setGraphic(imageView);
            });
            button.setGraphic(new ImageView(Utility.getFxImage("Image/PieDisk.png")));
        }
    }
    private void setFolderTree(){
        FolderPane folderPane = FolderPane.getInstance();
        folderAnchorPanel.getChildren().add(folderPane);
        AnchorPane.setBottomAnchor(folderPane,0.0);
        AnchorPane.setTopAnchor(folderPane,0.0);
        AnchorPane.setRightAnchor(folderPane,0.0);
        AnchorPane.setRightAnchor(folderPane,0.0);
    }
    private void initDiskUsageView(){
        scrollPanel.setContent(diskUsageView);
        diskUsageView.getChildren().clear();
        diskUsageView.prefHeightProperty().bind(scrollPanel.heightProperty());
        diskUsageView.prefWidthProperty().bind(scrollPanel.widthProperty());
        diskUsageView.setPadding(new Insets(5));
        diskUsageView.setHgap(5);
        diskUsageView.setVgap(5);
        updateDiskUsageView();
    }
    private void updateFileView(DirectoryEntry de) throws Exception {
        if(de.isFile()){
            fileViewPane.getChildren().clear();
            fileViewPane.getChildren().add(new Label("这是一个可执行文件"));
            return;}
        updateFileView((de.getPath().getAbsolutePath()));
    }
    private void updateFileView(String path) throws Exception {
        /*
        TODO:当在文件视图点击时 目录树也发生相应变化
         */
        fileViewPane.getChildren().clear();//清空文件视图
        Directory directory=new Directory(path);
        for(DirectoryEntry tmp:directory.getChildren()){
            if(tmp.isFile()){
                ImageView imageView=new ImageView(Utility.getFxImage("Image/Executable.png"));
                imageView.setFitHeight(35);
                imageView.setFitWidth(35);
                Button button = new Button(tmp.getProperty().getName(),imageView);
                button.setContentDisplay(ContentDisplay.TOP);
                button.setStyle("-fx-background-color:transparent");
                button.setOnMouseClicked(new EventHandler<MouseEvent>() {
                    @Override
                    public void handle(MouseEvent mouseEvent) {
                        if(mouseEvent.getButton().equals(MouseButton.PRIMARY)){
                            if(mouseEvent.getClickCount()==2){
                                //TODO:文件视图中可执行文件被点击时的操作
                                try {
                                    System.out.printf(tmp.getPath().getAbsolutePath()+'\n');
                                    FileManager.INSTANCE.executeFile(tmp.getPath().getAbsolutePath());
                                } catch (Exception e) {
                                    throw new RuntimeException(e);
                                }
                            }
                        }
                    }
                });
                fileViewPane.getChildren().add(button);
            }else if(tmp.isDirectory()){
                ImageView imageView=new ImageView(Utility.getFxImage("Image/Files.png"));
                imageView.setFitHeight(35);
                imageView.setFitWidth(35);
                Button button = new Button(tmp.getProperty().getName(),imageView);
                button.setContentDisplay(ContentDisplay.TOP);
                button.setStyle("-fx-background-color:transparent");
                button.setOnMouseClicked(new EventHandler<MouseEvent>() {
                    @Override
                    public void handle(MouseEvent mouseEvent) {
                        if(mouseEvent.getButton().equals(MouseButton.PRIMARY)){
                            if(mouseEvent.getClickCount()==2){
                                try {
                                    fileViewPath.setText("C:"+tmp.getPath().getAbsolutePath());
                                    updateFileView(tmp.getPath().getAbsolutePath());
                                } catch (Exception e) {
                                    throw new RuntimeException(e);
                                }
                            }
                        }
                    }
                });
                fileViewPane.getChildren().add(button);
            }
        }
    }
    private void showInfoOnConsole(String s,Color color){
        ensureVisible(consolePane,inputBox);//每打印一次就要确定输入框的位置
        Label label=new Label(s);
        label.setTextFill(color);
        label.setFont(new Font("Arial",12));
        historyBox.getChildren().add(label);
    }
    public void keepFocusOnTextField(){
        inputBox.requestFocus();
    }
    private void ensureVisible(ScrollPane pane, Node node) {
        //TODO:失效了？？？
        double height = pane.getContent().getBoundsInLocal().getHeight();
        double y = node.getBoundsInParent().getMaxY();
        pane.setVvalue(y/height);
        node.requestFocus();
    }
    private void changePreInputBox(String path){
        preInputBox.setText("C:"+path+">");
        fileViewPath.setText("C:"+path);
    }
}
